/**
 * @file DynamicArray.h
 * @author 申飞麟
 * @brief 动态数组头文件
 * @date 2025.1.31
 */

#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <inttypes.h>
#include <string.h>
#include "DynamicArray.h"

/**
 * @brief 动态数组创建
 * @param arr 动态数组指针
 * @param length 动态数组成员数
 * @return 内存分配成功返回 DYNAMICARRAY_NOERROR，内存分配失败失败返回 DYNAMICARRAY_ERROR_NOMALLOC
 */
DynamicArrayStatus DynamicArrayCreate(DynamicArray *arr, const size_t length)
{
    arr->length = length;
    arr->pdata = (int32_t *)malloc(length * sizeof(int32_t)); // 内存分配
    if (arr->pdata == NULL)                                   // 判断指针是否为空
    {
        return DYNAMICARRAY_ERROR_NOMALLOC;
    }
    return DYNAMICARRAY_NOERROR;
}

/**
 * @brief 动态数组删除
 * @param arr 动态数组指针
 */
void DynamicArrayDelete(DynamicArray *arr)
{
    free(arr->pdata);
    arr->pdata = NULL; // 防止指针悬挂
}

/**
 * @brief 向动态数组内填入数据
 * @param arr 动态数组指针
 * @param ID 动态数组序号
 * @param value 填入的数据
 * @return 填入成功返回 DYNAMICARRAY_NOERROR，数组溢出返回 DYNAMICARRAY_ERROR_OVERFLOW
 */
DynamicArrayStatus DynamicArraySet(DynamicArray *arr, const size_t ID, const int32_t value)
{
    if (ID >= arr->length) // 判断数组是否溢出
    {
        return DYNAMICARRAY_ERROR_OVERFLOW;
    }
    arr->pdata[ID] = value; // 填入数字
    return DYNAMICARRAY_NOERROR;
}

/**
 * @brief 获取动态数组数据
 * @param arr 动态数组指针
 * @param ID 动态数组序号
 * @param value 接收拷贝的指针
 * @return 获取成功返回 DYNAMICARRAY_NOERROR，序号不正确返回 DYNAMICARRAY_ERROR_OVERFLOW，指针为空返回 DYNAMICARRAY_ERROR_PNULL
 */
DynamicArrayStatus DynamicArrayGet(DynamicArray *arr, const size_t ID, int32_t *value)
{
    if (ID >= arr->length) // 判断数组是否溢出
    {
        return DYNAMICARRAY_ERROR_OVERFLOW;
    }
    if (value == NULL) // 判断指针是否为空
    {
        return DYNAMICARRAY_ERROR_PNULL;
    }
    *value = arr->pdata[ID]; // 读取数据
    return DYNAMICARRAY_NOERROR;
}

/**
 * @brief 动态数组开头插入元素
 * @param arr 动态数组指针
 * @param value 插入的元素
 * @return 插入成功返回 DYNAMICARRAY_NOERROR，内存分配失败返回 DYNAMICARRAY_ERROR_NOMALLOC
 */
DynamicArrayStatus DynamicArrayAddStart(DynamicArray *arr, const int32_t value)
{
    arr->pdata = (int32_t *)realloc(arr->pdata, (arr->length + 1) * sizeof(int32_t)); // 内存重新分配
    if (arr->pdata == NULL)                                                           // 判断指针是否为空
    {
        free(arr->pdata);
        return DYNAMICARRAY_ERROR_NOMALLOC;
    }
    for (int8_t i = arr->length; i > 0; i--) // 原数组后移一位
    {
        arr->pdata[i] = arr->pdata[i - 1];
    }
    arr->pdata[0] = value; // 开头插入数据
    arr->length++;
    return DYNAMICARRAY_NOERROR;
}

/**
 * @brief 动态数组末尾插入元素
 * @param arr 动态数组指针
 * @param value 插入的元素
 * @return 插入成功返回 DYNAMICARRAY_NOERROR，内存分配失败返回 DYNAMICARRAY_ERROR_NOMALLOC
 */
DynamicArrayStatus DynamicArrayAddEnd(DynamicArray *arr, const int32_t value)
{
    arr->pdata = (int32_t *)realloc(arr->pdata, (arr->length + 1) * sizeof(int32_t)); // 内存重新分配
    if (arr->pdata == NULL)                                                           // 判断指针是否为空
    {
        free(arr->pdata);
        return DYNAMICARRAY_ERROR_NOMALLOC;
    }
    arr->pdata[arr->length] = value; // 末尾填入数据
    arr->length++;
    return DYNAMICARRAY_NOERROR;
}

/**
 * @brief 改变动态数组长度
 * @param arr 动态数组指针
 * @param Changelength 改变的长度
 * @param overflow 溢出数据保存的指针
 * @return 改变成功返回 DYNAMICARRAY_NOERROR，内存分配失败返回 DYNAMICARRAY_ERROR_NOMALLOC，未定义返回 DYNAMICARRAY_ERROR_UNDEFINED
 */
DynamicArrayStatus DynamicArrayChange(DynamicArray *arr, const int32_t Changelength, DynamicArray *overflow)
{
    if (Changelength < 0) // 判断是否未定义
    {
        return DYNAMICARRAY_ERROR_UNDEFINED;
    }
    if (arr->length <= Changelength) // 判断是否延长数组
    {
        arr->pdata = (int32_t *)realloc(arr->pdata, Changelength * sizeof(int32_t)); // 内存重新分配
        if (arr->pdata == NULL)                                                      // 判断指针是否为空
        {
            free(arr->pdata);
            return DYNAMICARRAY_ERROR_NOMALLOC;
        }
        arr->length = Changelength; // 数组延长
        return DYNAMICARRAY_NOERROR;
    }
    if (overflow != NULL) // 判断溢出的数据是否保存
    {
        overflow->length = (arr->length) - Changelength;
        memcpy(overflow->pdata, (arr->pdata) + Changelength, (overflow->length) * sizeof(int32_t)); // 将溢出的数据保存到 overflow 数组中
    }
    if (Changelength == 0) // 判断数组长度是否为 0
    {
        free(arr->pdata);
        arr->length = 0;
        return DYNAMICARRAY_NOERROR;
    }

    arr->pdata = (int32_t *)realloc(arr->pdata, Changelength * sizeof(int32_t)); // 内存重新分配
    if (arr->pdata == NULL)                                                      // 判断指针是否为空
    {
        free(arr->pdata);
        return DYNAMICARRAY_ERROR_NOMALLOC;
    }
    arr->length = Changelength; // 数组缩短
    return DYNAMICARRAY_NOERROR;
}

/**
 * @brief 遍历数组
 * @param arr 动态数组指针
 * @return 返回数组内元素
 */
void DynamicArrayTraverse(DynamicArray *arr)
{
    for (int32_t i = 0; i < arr->length; i++)
    {
        printf("%" PRId32 "\t", arr->pdata[i]);
    }
    printf("\n");
}
